﻿Ext.lib.Container = Ext.extend(Ext.Component, {

    //自动销毁
    autoDestroy: true,

    //默认子组件类型
    defaultType: 'panel',

    //表示是容器
    isContainer: true,

    //组件样式前缀，用于组合成样式类的名称
    baseCls: 'x-container',


    bubbleEvents: ['add', 'remove'],


    initComponent: function () {
        this.addEvents(

            'afterlayout',

            'beforeadd',

            'beforeremove',

            'add',

            'remove',

            'beforecardswitch',

            'cardswitch'
        );


        this.layoutOnShow = new Ext.util.MixedCollection();
        Ext.lib.Container.superclass.initComponent.call(this);

        //将子组件信息放到内部集合中
        this.initItems();
    },

    //将子组件信息放到内部集合中
    initItems: function () {
        var items = this.items;

        //子组件集合
        this.items = new Ext.util.MixedCollection(false, this.getComponentId);

        if (items) {
            if (!Ext.isArray(items)) {
                items = [items];
            }

            this.add(items);//将子组件放入内部集合
        }
    },

    //渲染后的操作
    afterRender: function () {

        //获取布局对象，如果没有布局对象则新建一个，默认为容器布局对象
        this.getLayout();

        //调用父类的同名方法
        Ext.lib.Container.superclass.afterRender.apply(this, arguments);
    },

    //设置布局对象
    setLayout: function (layout) {
        var currentLayout = this.layout;

        //删除原布局对象与容器的关联
        if (currentLayout && currentLayout.isLayout && currentLayout != layout) {
            currentLayout.setOwner(null);
        }

        //设置新布局对象与容器的关联
        this.layout = layout;
        layout.setOwner(this);
    },

    //获取布局对象，如果没有布局对象则新建一个，默认为容器布局对象
    getLayout: function () {
        if (!this.layout || !this.layout.isLayout) {
            this.setLayout(Ext.layout.LayoutManager.create(this.layout, 'autocontainer'));
        }

        return this.layout;
    },

    //开始布局
    doLayout: function () {
        var layout = this.getLayout();

        if (this.rendered && layout) {
            layout.layout();
        }

        return this;
    },

    //触发布局后事件
    afterLayout: function (layout) {
        this.fireEvent('afterlayout', this, layout);
    },

    //创建子组件实例，以数组形式返回
    prepareItems: function (items, applyDefaults) {
        if (!Ext.isArray(items)) {
            items = [items];
        }


        var item, i, ln;

        for (i = 0, ln = items.length; i < ln; i++) {
            item = items[i];

            //如果默认子组件信息有效
            if (applyDefaults) {
                //将默认子组件信息以不覆盖的方式添加到子组件或子组件信息中
                item = this.applyDefaults(item);
            }

            //根据子组件信息创建子组件实例
            items[i] = this.lookupComponent(item);
        }

        return items;
    },

    //将默认子组件信息以不覆盖的方式添加到子组件或子组件信息中
    applyDefaults: function (config) {
        var defaults = this.defaults;

        //如果指定了默认子组件
        if (defaults) {
            if (Ext.isFunction(defaults)) {
                defaults = defaults.call(this, config);
            }

            //如果传人的是子组件的id
            if (Ext.isString(config)) {
                config = Ext.ComponentMgr.get(config);//获取子组件实例
                Ext.apply(config, defaults);
            } 
            //否则如果子组件是配置对象
            else if (!config.isComponent) {
                Ext.applyIf(config, defaults);//将默认的子组件属性以不覆盖的方式赋予当前子组件
            } 
            else {
                Ext.apply(config, defaults); //将默认的子组件属性以覆盖的方式赋予当前子组件
            }
        }

        return config;
    },

    //根据子组件信息创建子组件实例
    lookupComponent: function (comp) {
        if (Ext.isString(comp)) {
            return Ext.ComponentMgr.get(comp);//根据子组件id获取子组件实例
        } else {
            return this.createComponent(comp);//根据子组件信息创建子组件实例
        }
        return comp;
    },

    //创建组件实例
    createComponent: function (config, defaultType) {
        if (config.isComponent) {
            return config;
        }
        //创建组件实例
        return Ext.create(config, defaultType || this.defaultType);
    },


    getComponentId: function (comp) {
        return comp.getItemId();
    },

    //将子组件放入内部集合
    add: function () {
        var args = Array.prototype.slice.call(arguments),
            index = -1;

        if (typeof args[0] == 'number') {
            index = args.shift();
        }

        var hasMultipleArgs = args.length > 1;

        //如果参数传来多个子组件，或者传来一个装着子组件的数组
        if (hasMultipleArgs || Ext.isArray(args[0])) {
            var items = hasMultipleArgs ? args : args[0],
                results = [],
                i, ln, item;

            //将所有子组件放入集合
            for (i = 0, ln = items.length; i < ln; i++) {
                item = items[i];
                if (!item) {
                    throw "Trying to add a null item as a child of Container with itemId/id: " + this.getItemId();
                }

                if (index != -1) {
                    item = this.add(index + i, item);//调用自身
                } else {
                    item = this.add(item); //调用自身
                }
                results.push(item);
            }

            return results;
        }

        //创建子组件实例，以数组形式返回（只有一个元素）
        var cmp = this.prepareItems(args[0], true)[0];//获取第一个子组件实例

        index = (index !== -1) ? index : this.items.length;

        //将子组件加入容器
        if (this.fireEvent('beforeadd', this, cmp, index) !== false && this.onBeforeAdd(cmp) !== false) {

            //在集合的指定位置插入子组件
            this.items.insert(index, cmp);

            //使子组件关联该容器
            cmp.onAdded(this, index);
            this.onAdd(cmp, index);
            this.fireEvent('add', this, cmp, index);
        }

        return cmp;
    },

    onAdd: Ext.emptyFn,
    onRemove: Ext.emptyFn,

    //将子组件插入到容器指定位置
    insert: function (index, comp) {
        return this.add(index, comp);
    },

    //将子组件加入容器前的准备工作
    onBeforeAdd: function (item) {

        //如果子组件是其他容器的子组件
        if (item.ownerCt) {
            item.ownerCt.remove(item, false);//将子组件从其他容器中移除
        }

        //是否绘制子组件边框
        if (this.hideBorders === true) {
            item.border = (item.border === true);
        }
    },

    //移除子组件
    remove: function (comp, autoDestroy) {
        var c = this.getComponent(comp); //根据参数获取该容器的子组件

        //如果容器没有改子组件，给出警告信息
        if (!c) {
            console.warn("Attempted to remove a component that does not exist. Ext.Container: remove takes an argument of the component to remove. cmp.remove() is incorrect usage.");
        }

        if (c && this.fireEvent('beforeremove', this, c) !== false) {

            this.doRemove(c, autoDestroy);//移除子组件

            this.fireEvent('remove', this, c);
        }

        return c;
    },

    //移除子组件
    doRemove: function (component, autoDestroy) {
        var layout = this.layout,
            hasLayout = layout && this.rendered;

        //将子组件从集合中移除
        this.items.remove(component);
        component.onRemoved(); //将子组件与容器的关联移除

        if (hasLayout) {
            layout.onRemove(component);//将子组件与容器布局类的关联移除
        }

        this.onRemove(component, autoDestroy);

        if (autoDestroy === true || (autoDestroy !== false && this.autoDestroy)) {
            component.destroy();//销毁子组件
        }

        if (hasLayout && !autoDestroy) {
            layout.afterRemove(component);//布局移除组件的后续操作，比如移除在布局中定义的样式
        }
    },

    //移除容器的所有子组件
    removeAll: function (autoDestroy) {
        var item,
            removeItems = this.items.items.slice(),
            items = [],
            ln = removeItems.length,
            i;

        for (i = 0; i < ln; i++) {
            item = removeItems[i];
            this.remove(item, autoDestroy);

            if (item.ownerCt !== this) {
                items.push(item);
            }
        }

        return items;
    },




    //获取所有下级组件（包括子组件的子组件）
    getRefItems: function (deep) {
        var items = this.items.items.slice(),
            ln = items.length,
            i, item;

        if (deep) {
            for (i = 0; i < ln; i++) {
                item = items[i];

                if (item.getRefItems) {
                    items = items.concat(item.getRefItems(true));
                }
            }
        }

        return items;
    },

    //根据参数获取该容器的子组件
    getComponent: function (comp) {
        if (Ext.isObject(comp)) {
            comp = comp.getItemId();//参数的组件id
        }

        return this.items.get(comp);//根据组件id从该容器中获取子组件
    },


    query: function (selector) {
        return Ext.ComponentQuery.query(selector, this);
    },


    child: function (selector) {
        return this.query('> ' + selector)[0] || null;
    },



    down: function (selector) {
        return this.query(selector)[0] || null;
    },

    //显示容器
    show: function () {

        //显示容器组件
        Ext.lib.Container.superclass.show.apply(this, arguments);

        var layoutCollection = this.layoutOnShow,
            ln = layoutCollection.getCount(),
            i = 0,
            needsLayout,
            item;

        for (; i < ln; i++) {
            item = layoutCollection.get(i);
            needsLayout = item.needsLayout;

            if (Ext.isObject(needsLayout)) {
                item.doComponentLayout(needsLayout.width, needsLayout.height, needsLayout.isSetSize);
            }
        }

        layoutCollection.clear();
    },

    //销毁容器前的准备工作
    beforeDestroy: function () {
        var items = this.items,
            c;

        //移除子组件
        if (items) {
            while ((c = items.first())) {
                this.doRemove(c, true);
            }
        }

        //销毁布局类
        Ext.destroy(this.layout);
        Ext.lib.Container.superclass.beforeDestroy.call(this);
    }
});
